home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Light ROM 1
/
LIGHT-ROM 1 (Amiga Library Services)(1994).iso
/
ffdisks
/
d879.lha
/
DiskTest
/
Source
/
ts.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-18
|
10KB
|
398 lines
/*-------------------------------------*
| File: TS.c - Text scroller routines |
+-------------------------------------------------------------*
| These routines were inspired from an example due to Martin |
| Taillefer and published on AmigaMail; although the original |
| routines have been heavily modified, I am in debt with M.T. |
+---------------------------------------------------------+---*
| Author: Maurizio Loreti, aka MLO or I3NOO. |
| Address: University of Padova - Department of Physics |
| Via F. Marzolo, 8 - 35131 PADOVA - Italy |
| Phone: (39)(49) 844-313 FAX: (39)(49) 844-245 |
| E-Mail: loreti@padova.infn.it (TCP/IP) |
| Home: Via G. Donizetti 6 - 35010 CADONEGHE (PD) - Italy |
*---------------------------------------------------------*/
/**
| #includes
**/
#include <stddef.h> /* Standard library */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h> /* AmigaDOS specific */
#include <clib/graphics_protos.h>
#include <clib/layers_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/intuition_protos.h>
#include "main.h" /* Local stuff */
#include "ts.h"
#include "ext.h"
void AddLine(
char *s,
size_t n,
BOOL update
){
/**
| Adds the string "s" ("n" bytes long) to our document:
| a new "Line" structure is added to the linked list, and
| filled; if "update" is TRUE, the text is scrolled to
| display the last line and updated.
**/
Line *pL;
if ((pL = malloc(sizeof(Line) + n)) == NULL) {
Error("No memory for Line");
}
pL->sl_Length = n;
strcpy(pL->sl_Text, s);
pL->sl_Forw = NULL;
if ((pL->sl_Back = lastLine) == NULL) {
firstLine = pL;
} else {
lastLine->sl_Forw = pL;
}
lastLine = pL;
numLines++;
if (update) {
if (numLines > linesVisible) {
topLine = numLines - linesVisible;
} else {
topLine = 0;
}
UpdateScroller();
}
}
void BusyState(
BOOL state
){
/**
| Whenever the application is busy, this function should be called
| as BusyState(TRUE); this will change the pointer to a default
| OS 2.0 busy-pointer too, to tell the user that we are not
| listening to the IDCMP's for awhile. When finished, call
| BusyState(FALSE).
**/
static UWORD __chip waitPointer[] = {
0x0000, 0x0000, 0x0400, 0x07C0, 0x0000, 0x07C0, 0x0100, 0x0380,
0x0000, 0x07E0, 0x07C0, 0x1FF8, 0x1FF0, 0x3FEC, 0x3FF8, 0x7FDE,
0x3FF8, 0x7FBE, 0x7FFC, 0xFF7F, 0x7EFC, 0xFFFF, 0x7FFC, 0xFFFF,
0x3FF8, 0x7FFE, 0x3FF8, 0x7FFE, 0x1FF0, 0x3FFC, 0x07C0, 0x1FF8,
0x0000, 0x07E0, 0x0000, 0x0000
};
if (state == TRUE) {
SetPointer(pWind, waitPointer, 16, 16, -6, 0);
} else {
ClearPointer(pWind);
}
if (pWind->WLayer->Flags & LAYERREFRESH) {
RefreshView(TRUE);
}
}
void ClearText(
BOOL update
){
/**
| This procedure free()s all the linked list holding the
| scrolled text. If "update" is TRUE, the window scrolling
| region is really cleared.
**/
Line *pL;
for (pL=firstLine; pL!=NULL; ) {
Line *next = pL->sl_Forw;
free(pL);
pL = next;
}
firstLine = lastLine = NULL;
numLines = topLine = 0;
if (update) {
SetScroller(pWind, pScroller, linesVisible, numLines, topLine);
RefreshView(TRUE);
}
}
void InitScroller(void)
{
/**
| Scroller initialisation.
| - memory is obtained to hold a copy of the window raster port to
| be used for clearing (the originel raster port is used for
| rendering); this speeds up these operations avoiding SetAPen() etc.
| - some local global variables are initialised;
| - the scrolling region is drawn (with the help text loaded in the
| initialisation routines).
**/
memcpy(pClearRP, (pRP = pWind->RPort), sizeof(struct RastPort));
SetDrMd(pClearRP, JAM2);
SetAPen(pClearRP, 0);
SetAPen(pRP, 1);
fontWidth = pWind->RPort->Font->tf_XSize;
fontHeight = pWind->RPort->Font->tf_YSize;
bevelLeft = pWind->BorderLeft + BEVEL_LEFT;
bevelTop = pWind->BorderTop + BEVEL_TOP;
bevelWidth = BEVEL_WIDTH;
bevelHeight = BEVEL_HEIGHT;
textLeft = bevelLeft + TEXT_XOFFSET;
textTop = bevelTop + TEXT_YOFFSET;
viewWidth = (USHORT) (bevelWidth - 2 * (TEXT_XOFFSET) - 1);
viewHeight = (USHORT) (bevelHeight - 2 * (TEXT_YOFFSET) - 1);
columnsVisible = viewWidth / fontWidth;
linesVisible = viewHeight / fontHeight;
usefulWidth = (USHORT) (columnsVisible * fontWidth);
RefreshView(TRUE);
SetScroller(pWind, pScroller, linesVisible, numLines, topLine);
}
void LastLine(
char *s,
size_t n
){
/**
| A line is drawn at the end of the text, but NOT inserted
| in the linked list; it will then be overdrawn from the next
| AddLine()d or LastLine()d text; the text is scrolled if needed,
| to display the bottom line.
| LastLine() here is only used to display the
| "reading track X head Y" text.
| "s" is the string to be displayed, "n" bytes long.
**/
USHORT y;
if (numLines >= linesVisible) {
topLine = numLines - linesVisible + 1;
UpdateScroller();
y = linesVisible;
} else {
y = numLines - topLine + 1;
}
y = (USHORT) (textTop + pRP->TxBaseline + fontHeight * (y - 1));
RenderLine(textLeft, y, usefulWidth, s, n);
}
void RefreshView(
BOOL damage
){
/**
| This function performs most of the rendering work needed.
| It looks at the current window size and adjusts its rendering
| variables in consequence; then, if the "damage" parameter is
| TRUE, this routine explicitly erases any area of the display
| in which we will not be rendering in the rendering loop: this
| erases any left over characters that could be there if the
| user sizes or rearrange the window. Finally, the routine
| determines which lines of the display need to be updated,
| and goes on to do it.
**/
USHORT i;
Line *pL;
USHORT y;
/**
| What is the top line to be rendered?
**/
if (linesVisible > numLines) {
usefulHeight = (USHORT) (numLines * fontHeight);
topLine = 0;
} else {
usefulHeight = (USHORT) (linesVisible * fontHeight);
if (topLine + linesVisible > numLines) {
topLine = numLines - linesVisible;
}
}
/**
| If the layer has been damaged (and the window is to be refreshed),
| this is handled now (the gadgetry is already OK at this moment).
**/
if (damage) {
RectFill(pClearRP,
bevelLeft - 1,
bevelTop - 1,
bevelLeft + bevelWidth,
bevelTop + bevelHeight);
DrawBevelBox(pRP,
bevelLeft, bevelTop,
bevelWidth, bevelHeight,
GT_VisualInfo, pVI,
TAG_END);
}
/**
| Do we have something to render? If yes, we find the pointer to the
| top line text, starting from the top or the bottom of the list.
**/
if (usefulHeight && usefulWidth) {
int n;
if ((n = numLines - (topLine + 1)) < topLine) {
pL = ScanList(firstLine, topLine);
} else {
pL = ScanList(lastLine, -n);
}
y = (USHORT) (textTop + pRP->TxBaseline - fontHeight);
if (damage || (topLine >= oldTopLine + linesVisible - 1) ||
((oldTopLine > linesVisible) &&
(topLine <= oldTopLine - linesVisible + 1))) {
i = linesVisible;
} else if (topLine < oldTopLine) {
ScrollRaster(pRP,
0, -((long) (oldTopLine - topLine) * fontHeight),
textLeft,
textTop,
textLeft + usefulWidth - 1,
textTop + usefulHeight - 1);
i = oldTopLine - topLine;
} else if (topLine > oldTopLine) {
ScrollRaster(pRP,
0, ((topLine - oldTopLine) * fontHeight),
textLeft,
textTop,
textLeft + usefulWidth - 1,
textTop + usefulHeight - 1);
for (i = linesVisible - (topLine - oldTopLine);
pL->sl_Forw != NULL && i;
i--) {
pL = pL->sl_Forw;
}
y += (USHORT) (fontHeight * (linesVisible - (topLine - oldTopLine)));
i = topLine - oldTopLine;
} else if (oldNumLines < numLines && numLines <= linesVisible) {
for (i = oldNumLines; pL->sl_Forw != NULL && i; i--) {
pL = pL->sl_Forw;
}
y += (USHORT) (fontHeight * oldNumLines);
i = numLines - oldNumLines;
} else {
i = 0;
}
while (i-- && pL != NULL) {
y += fontHeight;
RenderLine(textLeft, y, usefulWidth, pL->sl_Text, pL->sl_Length);
pL = pL->sl_Forw;
}
}
oldTopLine = topLine;
oldNumLines = numLines;
}
void SetTopLine(
UWORD n
){
/**
| Sets the top line of the scroller text to "n".
**/
if (topLine != n) {
topLine = n;
RefreshView(FALSE);
}
}
/*-------------------------- Local Procedures --------------------------*/
static void RenderLine(
USHORT x,
USHORT y,
USHORT w,
char *text,
size_t len
){
/**
| Render a single line of text ("text", "len" characters
| long) at the given position "x","y" (pixels). "w" is the
| length (pixels) of the rendering region.
**/
Move(pRP, x, y);
if (len > columnsVisible) {
len = columnsVisible;
}
(void) Text(pRP, text, len);
if (len < columnsVisible) {
RectFill(pClearRP,
pRP->cp_x,
y - pRP->TxBaseline,
x + w - 1,
y - pRP->TxBaseline + fontHeight - 1);
}
}
static void SetScroller(
struct Window *pW,
struct Gadget *pG,
USHORT lV,
USHORT nL,
USHORT tL
){
/**
| Adjust the scroller gadget to reflect the current setting:
| "lV" lines visible, "nL" total lines and "tL" number of the
| top line.
**/
GT_SetGadgetAttrs(pG, pW, NULL,
GTSC_Visible, lV,
GTSC_Total, nL,
GTSC_Top, tL,
TAG_DONE);
}
static Line *ScanList(
register Line *pL,
register int n
){
register Line *pNew;
if (n > 0) {
while (n-- && (pNew = pL->sl_Forw) != NULL) pL = pNew;
} else if (n < 0) {
while (n++ && (pNew = pL->sl_Back) != NULL) pL = pNew;
}
return pL;
}
static void UpdateScroller(void)
{
/**
| Updates the text scrolling region, reflecting
| the current settings.
**/
SetScroller(pWind, pScroller, linesVisible, numLines, topLine);
RefreshView(FALSE);
}